using System;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Linq;
using System.Web.Security;
using Less.Core.Model;
using Less.SRV;

namespace Less.Web.Security
{
    public class LessRoleProvider : RoleProvider
    {
        private readonly SecuritySRV securitySRV = new SecuritySRV();
        #region Overrides of RoleProvider
        public override string ApplicationName { get; set; }
        public override bool IsUserInRole(string username, string roleName)
        {
            if (username == null)
            {
                throw new ArgumentNullException("username");
            }
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            return this.securitySRV.IsUserInRole(username, roleName);
        }

        public override string[] GetRolesForUser(string username)
        {
            if (username == null)
            {
                throw new ArgumentNullException("username");
            }
            List<Role> roles = this.securitySRV.SelectRolesByUserName(username);
            return roles != null ? roles.Select(r => r.Name).ToArray() : new string[] {};
        }

        public override void CreateRole(string roleName)
        {
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            this.securitySRV.InsertRoleByName(roleName);
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            if (throwOnPopulatedRole && GetUsersInRole(roleName).Length > 0)
            {
                throw new ProviderException("Cannot delete a populated role");
            }
            return this.securitySRV.DeleteRoleByName(roleName);
        }

        public override bool RoleExists(string roleName)
        {
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            return this.securitySRV.SelectByName(roleName) != null;
        }

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            if (usernames.IsNullOrEmpty())
            {
                throw new ArgumentNullException("usernames");
            }
            if (roleNames.IsNullOrEmpty())
            {
                throw new ArgumentNullException("roleNames");
            }
            this.securitySRV.AddUsersToRoles(usernames, roleNames);
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            if (usernames.IsNullOrEmpty())
            {
                throw new ArgumentNullException("usernames");
            }
            if (roleNames.IsNullOrEmpty())
            {
                throw new ArgumentNullException("roleNames");
            }
            this.securitySRV.RemoveUsersFromRoles(usernames, roleNames);
        }

        public override string[] GetUsersInRole(string roleName)
        {
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            List<User> users = this.securitySRV.SelectUsersByRoleName(roleName);
            return users != null ? users.Select(u => u.UserName).ToArray() : new string[] {};
        }

        public override string[] GetAllRoles()
        {
            List<Role> roles = this.securitySRV.GetAllRoles();
            return roles != null ? roles.Select(r => r.Name).ToArray() : new string[] {};
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            if (roleName == null)
            {
                throw new ArgumentNullException("roleName");
            }
            if (usernameToMatch == null)
            {
                throw new ArgumentNullException("usernameToMatch");
            }
            List<User> users = this.securitySRV.SelectUsersByRoleName(roleName);
            return users != null ? users.Where(u => u.UserName.Contains(usernameToMatch)).Select(u => u.UserName).ToArray() : new string[] {};
        }
        #endregion
    }
}